package raft

// 用于保存和读取 Raft 的状态信息
// support for Raft and kvraft to save persistent
// Raft state (log &c) and k/v server snapshots.
//
// we will use the original persister.go to test your code for grading.
// so, while you can modify this code to help you debug, please
// test with the original before submitting.
//

import (
	"bytes"
	"os"
	"sync"
)

type Persister struct {
	mu        sync.Mutex
	raftstate []byte
	snapshot  []byte
	name      string
}

func MakePersister(name string) *Persister {
	n := &Persister{}
	n.name = name
	return n
}

// SaveToFile 持久化 raftstate 到文件
func (ps *Persister) SaveToFile(filename string) error {
	// 打开或创建文件
	file, err := os.OpenFile(filename, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0644)
	if err != nil {
		return err
	}
	defer file.Close()

	// 将数据写入文件
	if _, err := file.Write(ps.raftstate); err != nil {
		return err
	}

	return nil
}

// ReadFromFile 从文件中读取 raftstate
func (ps *Persister) ReadFromFile(filename string) error {
	// 打开文件
	file, err := os.Open(filename)
	if err != nil {
		return err
	}
	defer file.Close()

	// 读取文件内容
	var data bytes.Buffer
	_, err = data.ReadFrom(file)
	if err != nil {
		return err
	}

	// 解码数据到 ps.raftstate
	ps.raftstate = data.Bytes()

	return nil
}

// Copy 是 Persister 对象之间的值拷贝函数
func (ps *Persister) Copy() *Persister {
	ps.mu.Lock()
	defer ps.mu.Unlock()
	np := MakePersister(ps.name)
	np.raftstate = ps.raftstate
	np.snapshot = ps.snapshot
	return np
}

// SaveRaftState 保存 raftstate
// TODO: 待实现
func (ps *Persister) SaveRaftState(state []byte) {
	ps.mu.Lock()
	defer ps.mu.Unlock()
	ps.raftstate = state
	ps.SaveToFile(ps.name + "raftstate.bin")
}

// ReadRaftState 获取 raftstate
func (ps *Persister) ReadRaftState() []byte {
	ps.mu.Lock()
	defer ps.mu.Unlock()
	ps.ReadFromFile(ps.name + "raftstate.bin")
	return ps.raftstate
}

// RaftStateSize 获取 raftstate 的大小
func (ps *Persister) RaftStateSize() int {
	ps.mu.Lock()
	defer ps.mu.Unlock()
	return len(ps.raftstate)
}

// SaveStateAndSnapshot 将 raftstate 和 snapshot 的保存过程封装为一个原子操作
func (ps *Persister) SaveStateAndSnapshot(state []byte, snapshot []byte) {
	ps.mu.Lock()
	defer ps.mu.Unlock()
	ps.raftstate = state
	ps.snapshot = snapshot
}

// ReadSnapshot 读取 snapshot
func (ps *Persister) ReadSnapshot() []byte {
	ps.mu.Lock()
	defer ps.mu.Unlock()
	return ps.snapshot
}

// SnapshotSize 获取 snapshot 大小
func (ps *Persister) SnapshotSize() int {
	ps.mu.Lock()
	defer ps.mu.Unlock()
	return len(ps.snapshot)
}
